package com.alibaba.dubbo.common.serialize.support.kryo;

import com.alibaba.dubbo.common.serialize.Cleanable;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Registration;
import com.esotericsoftware.kryo.pool.KryoPool;
import com.esotericsoftware.kryo.serializers.DefaultSerializers;
import com.esotericsoftware.kryo.serializers.MapSerializer;
import de.javakaffee.kryoserializers.*;

import java.lang.reflect.InvocationHandler;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;

/**
 * Created by sunlei on 2016/2/18.
 */
public class KryoFactory{

    private static KryoFactory INSTANCE=null;

    private static com.esotericsoftware.kryo.pool.KryoFactory factory;

    static {
        INSTANCE = new KryoFactory();
        factory = new com.esotericsoftware.kryo.pool.KryoFactory() {
            public Kryo create() {
                Kryo kryo = new CompatibleKryo();
                kryo.setRegistrationRequired(true);
                kryo.register(Map.class);
                kryo.register( Arrays.asList( "" ).getClass(), new ArraysAsListSerializer() );
                kryo.register(GregorianCalendar.class, new GregorianCalendarSerializer());
                kryo.register(InvocationHandler.class, new JdkProxySerializer());
                kryo.register(BigDecimal.class, new DefaultSerializers.BigDecimalSerializer());
                kryo.register(BigInteger.class, new DefaultSerializers.BigIntegerSerializer());
                kryo.register(Pattern.class, new RegexSerializer());
                kryo.register(BitSet.class, new BitSetSerializer());
                kryo.register(URI.class, new URISerializer());
                kryo.register(UUID.class, new UUIDSerializer());
                UnmodifiableCollectionsSerializer.registerSerializers(kryo);
                SynchronizedCollectionsSerializer.registerSerializers(kryo);

                // now just added some very common classes
                kryo.register(HashMap.class);
                kryo.register(ArrayList.class);
                kryo.register(LinkedList.class);
                kryo.register(HashSet.class);
                kryo.register(TreeSet.class);
                kryo.register(Hashtable.class);
                kryo.register(Date.class);
                kryo.register(Calendar.class);
                kryo.register(ConcurrentHashMap.class);
                kryo.register(SimpleDateFormat.class);
                kryo.register(GregorianCalendar.class);
                kryo.register(Vector.class);
                kryo.register(BitSet.class);
                kryo.register(StringBuffer.class);
                kryo.register(StringBuilder.class);
                kryo.register(Object.class);
                kryo.register(Object[].class);
                kryo.register(String[].class);
                kryo.register(byte[].class);
                kryo.register(char[].class);
                kryo.register(int[].class);
                kryo.register(float[].class);
                kryo.register(double[].class);

                return kryo;
            }
        };
    }

    public static KryoFactory getInstance(){
        return INSTANCE;
    }

    private static final KryoPool pool=new KryoPool.Builder(factory).build();

    public  Kryo create(){
        return pool.borrow();
    }

    public  void release(Kryo kryo){
        pool.release(kryo);
    }

}
